#!/usr/bin/python
#--*-- coding:UTF-8 --*--
#---------------------------------------------------
#  程序：本来库存监控 v1.0
#  版本：1.0
#  作者：Vanson
#  日期：2018-06-15 
#  环境：Python 2.7 Win10
#  功能：本来库存监控 支持多个商品监控 邮件通知 
#  声明：程序仅供技术交流，请勿用于商业及非法用途，
#        如产生法律纠纷与本人无关。
#---------------------------------------------------
import os, re, sys, urllib, requests, json, traceback, codecs, schedule, time
from pyquery import PyQuery as pq
from datetime import datetime
sys.path.append(sys.path[0] + '\exmail')
from exmail import exmail
reload(sys)
sys.setdefaultencoding('utf-8')


# 本来库存监控
class blInventory():

	# 初始化
	def __init__(self):
		# 初始化商品信息
		if os.path.exists(sys.path[0] + '\config\sysno.txt') :
			sysno = []
			# 读取商品信息
			for line in open(sys.path[0] + '\config\sysno.txt', 'r'):
				if (re.search('--', line) == None and re.search('\d+', line)):
					sysno.append(line.strip())
		if sysno:
			self.sysno = []
			for v in sysno:
				self.sysno.append(v.split(','))
			self.sysno = sorted(self.sysno, key=lambda d: d[1], reverse=False) # 根据区域排序
		else:
			self.printAndLog('sysno.txt没有有效信息...', 'ERRO')
			raw_input()
			exit()

		# 读取邮件信息
		if os.path.exists(sys.path[0] + '\config\mail.txt') :
			to_addr = []
			# 读取文件
			for line in open(sys.path[0] + '\config\mail.txt', 'r'):
				if (re.search('--', line) == None):
					to_addr.append(line.strip())

		if to_addr:
			self.to_addr = to_addr # 收件人
		else:
			self.printAndLog('mail.txt没有有效信息...', 'ERRO')
			raw_input()
			exit()

		self.headers = {
			'Accept'     : 'text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8',
			'referer'    : 'https://www.benlai.com/',
			'user-agent' : 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/66.0.3359.139 Safari/537.36'
		}
		self.inventory_url = 'http://www.benlai.com/NewCategory/GetBFDProductInfo' # 库存接口
		

	# 库存监测
	def check_inventory(self):
		content   = '' # 初始化邮件内容
		new_sysno = [] # 初始化新商品监控信息
		for k, v in enumerate(self.sysno):
			if (k == 0):
				# 第一次开始切换区域
				area = v[1]                                               # 保存地区避免重复切换
				self.requests_session = self.benlai_switch_site(v[1])     # 切换地区
			else:
				# 检测是同区就不切换区域
				if (v[1] != area):
					area = v[1]                                           # 保存地区避免重复切换
					self.requests_session = self.benlai_switch_site(v[1]) # 切换地区
			area_name    = self.get_area_name(v[1])                       # 地区名称
			product_info = self.get_product_info(v[0], v[1])     # 库存监测
			if (product_info):
				if (product_info[0] > 0):
					self.printAndLog('「 √ 」【{0}】{1}到货，库存{2}, 移除监控列表...'.format(area_name, product_info[1], product_info[0]), 'SUCC')
					content += '<p><span style="color:blue">' + product_info[1] + '</span><span style="color:red"> ￥' + str(product_info[2]) + '</span><span style="color:green"> 库存：' + str(product_info[0]) + '</span></p>'
				else:
					new_sysno.append('{0},{1}'.format(v[0], v[1])) # 无货的继续监控
					self.printAndLog('「 × 」【{0}】{1}无货...'.format(area_name, product_info[1]), 'FAIL')
			else:
				new_sysno.append('{0},{1}'.format(v[0], v[1])) # 错误的也继续监控
				self.printAndLog('「 × 」 {0},{1} [商品已下架,或数据有误]'.format(v[0], v[1]), 'ERRO')

		if (content):
			self.printAndLog('「 > 」 检测到商品到货，开始发送邮件通知...', 'INFO')
			self.send_mail(self.to_addr, '【Message】到货通知', content) # 发送通知
			# 重写sysno.txt 到货的去除监控
			with codecs.open(sys.path[0] + '\config\sysno.txt', 'w', 'utf_8_sig') as f:
				f.write('-- 格式:   sysno,地区(1华北, 2华南, 3华东) 例 : 357765,1\r\n-- 多个请回车换行') # 文件头
			with codecs.open(sys.path[0] + '\config\sysno.txt', 'a', 'utf_8_sig') as f:
				for v in new_sysno:
					f.write('\r\n' + v)
		printLogNoTime('------------------------------------------------------------------------------------------')

	@staticmethod
	def get_area_name(area):
		# 获取地区名称
		if area == '1':
			area_name = '华北'
		elif area == '2':
			area_name = '华南'
		elif area == '3':
			area_name = '华东'
		return area_name

	@staticmethod
	def send_mail(to_addr, title, content):
		# 发送邮件
		# to_addr [list]   收件人
		# title   [String] 标题
		# content [String] 内容(支持简单的html标签 css颜色)
		mail = exmail(to_addr, title, content)
		mail.send()

	# 获取库存
	def get_product_info(self, product_id, area):
 		product_list = str(product_id);
		if area == '1':
			product_list += ',3999,4000'   # 北京
		elif area == '2':
			product_list += ',13346,13347' # 深圳
		elif area == '3':
			product_list += ',11618,11619' # 上海

		data    = {'sysNoList' : product_list}  # post数据
		headers = {
			'Accept'           : '*/*',
			'referer'          : 'https://www.benlai.com/',
			'user-agent'       : 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/66.0.3359.139 Safari/537.36',
			'X-Requested-With' : 'XMLHttpRequest' # 必加异步头 不然获取会报错
		}

		result = self.requests_session.post(self.inventory_url, data = data, headers = headers)
		result = json.loads(result.text, encoding = 'UTF-8')
		if (result):
			inventory        = result[0]['Inventory'] if result[0]['Inventory'] else -1                       # 库存
			product_name     = result[0]['ProductName'] if result[0]['ProductName'] else ''                   # 商品名称
			product_nowprice = result[0]['ProductNowPrice'] if result[0]['ProductNowPrice'] else ''           # 现价
			return [inventory, product_name, product_nowprice]
		else:
			return []			 

	# 切换地区
	def benlai_switch_site(self, area):
		websiteSysNo  = '';
		deliverySysNo = '';
		# 1华北2北京 2华南246深圳 3华东120上海  切换地区
		if area == '1':
			websiteSysNo  = 1
			deliverySysNo = 2
		elif area == '2':
			websiteSysNo  = 2
			deliverySysNo = 246
		elif area == '3':
			websiteSysNo  = 3
			deliverySysNo = 120
		requests_session = requests.Session() # 保持请求链接
		requests_session.post('https://www.benlai.com/Account/SwitchSite', data = {'websiteSysNo': websiteSysNo, 'deliverySysNo': deliverySysNo}, headers = self.headers)
		return requests_session

	# 记录程序log
	@staticmethod
	def printAndLog(msg, boolean_print=True, msg_type='INFO'):
		if (boolean_print):
			print(datetime.now().strftime("%Y-%m-%d %H:%M:%S") + ' [' + msg_type + '] ' + msg.decode('utf-8').encode('gbk'))
		if os.path.exists(sys.path[0] + '\log\log.txt') == False:
			with codecs.open(sys.path[0] + '\log\log.txt', 'w', 'utf_8') as f:
				f.write(datetime.now().strftime("%Y-%m-%d %H:%M:%S") + ' [' + msg_type + '] ' + msg)
		else:
			with codecs.open(sys.path[0] + '\log\log.txt', 'a', 'utf_8') as f:
				f.write('\r\n' + datetime.now().strftime("%Y-%m-%d %H:%M:%S") + ' [' + msg_type + '] ' + msg)

def printLogNoTime(msg):
	print(msg.decode('utf-8').encode('gbk'))
	if os.path.exists(sys.path[0] + '\log\log.txt') == False:
		with codecs.open(sys.path[0] + '\log\log.txt', 'w', 'utf_8') as f:
			f.write(msg)
	else:
		with codecs.open(sys.path[0] + '\log\log.txt', 'a', 'utf_8') as f:
			f.write('\r\n' + msg)

# 定时任务
def run():
	bl = blInventory()
	bl.check_inventory()



#-------- 程序入口处 ------------------ 
if __name__ == '__main__':
	os.system('cls')
	print u'''
#---------------------------------------------------#
#  程序：本来库存监控 v1.0                          #
#  版本：1.0                                        #
#  作者：Vanson                                     #
#  日期：2018-06-15                                 #
#  环境：Python 2.7 Win10                           #
#  功能：本来库存监控 支持多个商品监控 邮件通知     #
#  声明：程序仅供技术交流，请勿用于商业及非法用途， #
#        如产生法律纠纷与本人无关。                 # 
#---------------------------------------------------#
'''
	refresh_time = raw_input('请输入刷新间隔(秒) 直接回车默认60秒\r\n'.decode('utf-8').encode('gbk')).strip()
	if refresh_time.strip() == '':
		refresh_time = 60
	printLogNoTime('------------------------------------------------------------------------------------------')
	run()                                             # 先执行一次
	schedule.every(int(refresh_time)).seconds.do(run) # 之后固定频率执行
	while True:
		try:
			schedule.run_pending()
			time.sleep(1)
		except Exception as e:
			traceback.print_exc()
			raw_input()